#include "microApp.h"
#include "BussinessTerminalManage.h"
#include "sqlite3.h"
#include <dlfcn.h>

extern ob_context g_mqtt_ob;

//用于召测线程单例实现
static pthread_mutex_t app_status_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool app_status_thread_running = false;

/// @brief 插入app相关信息
/// @param param
/// @return
bool SqlAddAppInfo(IOTA_APP_CTRL param, char *filename)
{
    dzlog_info("SqlAddAppInfo start filename[%s]", filename);

    bool ret = false;
    sqlite3_stmt *stmt;
    char *str = filename;
    char app[256];
    char version[256];
    char application_title[64] = {0};

    // sys.nfoam-V1.2.1-20250117.pack  单架构应用名规范:appname-version-date.pack   appmname_version.tar.gz
    char delimiter[] = "-";
    int MAX_TOKENS = 10;
    int MAX_TOKEN_LEN = 20;
    char tokens[10][20];
    int token_count = 0;
    dzlog_info("SqlAddAppInfo start 1 str[%s]", str);
    // 使用strtok函数分割字符串
    char *token = strtok(str, delimiter);
    while (token != NULL && token_count < MAX_TOKENS)
    {
        dzlog_info("SqlAddAppInfo start 11 token[%s]", token);
        strncpy(tokens[token_count], token, MAX_TOKEN_LEN - 1);
        tokens[token_count][MAX_TOKEN_LEN - 1] = '\0'; // 确保字符串以null结尾
        token_count++;
        token = strtok(NULL, delimiter);
    }
    dzlog_info("SqlAddAppInfo start 2");
    if (token_count = 1)
    {
        // 包名并不符合规范
        strcpy(app, tokens[0]);
        strcpy(version, param.appVersion);
        dzlog_info("SqlAddAppInfo start 3");
    }
    else
    {
        strcpy(app, tokens[0]);
        if (param.appVersion == NULL || strlen(param.appVersion) == 0)
        {
            strcpy(version, tokens[1]);
        }
        else
        {
            strcpy(version, param.appVersion);
        }
        dzlog_info("SqlAddAppInfo start 4");
    }


    dzlog_info("SqlAddAppInfo start 5");
    // application_title为上报的应用名，理论上是平台下发的那个应用名，但如果为空，则用实际的应用名
    if (param.appName == NULL || strlen(param.appName) == 0)
    {
        strcpy(application_title, app);
    }
    else
    {
        strcpy(application_title, param.appName);
    }
    dzlog_info("SqlAddAppInfo start 6");
    const char *sql = "INSERT INTO APP_LIST (appid, fileid, appname, appversion, filename,istrustworthy,application_title) VALUES (?, ?, ?, ?, ?, ?, ?)";
    dzlog_info("SqlAddAppInfo start 7");
    int rc = sqlite3_prepare_v2(g_sqlite3_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_info("SqlAddAppInfo start 8");
        dzlog_error("SQL: %s error:%s\n", sql, sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    dzlog_info("SqlAddAppInfo param.appId[%s],app[%s],version[%s],application_title[%s]", param.appId, app, version, application_title);
    // 绑定参数的值
    sqlite3_bind_text(stmt, 1, param.appId, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, param.fileId, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, app, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 4, version, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 5, filename, -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 6, 1);
    sqlite3_bind_text(stmt, 7, application_title, -1, SQLITE_STATIC);
    dzlog_info("SqlAddAppInfo start 9");
    // 因为要3.14版本以上的sqlite支持，注释掉
    //  char *expanded_sql = sqlite3_expanded_sql(stmt);
    //  if (expanded_sql != NULL)
    //  {
    //      dzlog_debug("生成的 SQL 语句: %s\n", expanded_sql);
    //      sqlite3_free(expanded_sql);
    //  }

    // 执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("SQL error: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 重置预处理语句以便可重复使用
    sqlite3_reset(stmt);
    ret = true;
error:
    if (stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }
    return ret;
}

bool SqlAddAppInfo_V2(IOTA_APP_CTRL param, char *filename)
{
    bool ret = false;
    sqlite3_stmt *stmt;
    char *str = filename;
    char app[256];
    char version[256];
    char application_title[64] = {0};

    // sys.dbc_2_V1.2.1.tar.gz
    char delimiter[] = "_";
    int MAX_TOKENS = 10;
    int MAX_TOKEN_LEN = 20;
    char tokens[10][20];
    int token_count = 0;

    // 使用strtok函数分割字符串
    char *token = strtok(str, delimiter);
    while (token != NULL && token_count < MAX_TOKENS)
    {
        strncpy(tokens[token_count], token, MAX_TOKEN_LEN - 1);
        tokens[token_count][MAX_TOKEN_LEN - 1] = '\0'; // 确保字符串以null结尾
        token_count++;
        token = strtok(NULL, delimiter);
    }
    if (token_count < 3)
    {
        // 包名并不符合规范
        strcpy(version, param.appVersion);
        strcpy(app, param.appName);
    }
    else
    {
        strcpy(app, tokens[0]);
        if (param.appVersion == NULL || strlen(param.appVersion) == 0)
        {
            strcpy(version, tokens[2]);
        }
        else
        {
            strcpy(version, param.appVersion);
        }
    }


    // application_title为上报的应用名，理论上是平台下发的那个应用名，但如果为空，则用实际的应用名
    if (param.appName == NULL || strlen(param.appName) == 0)
    {
        strcpy(application_title, app);
    }
    else
    {
        strcpy(application_title, param.appName);
    }

    const char *sql = "INSERT INTO APP_LIST (appid, fileid, appname, appversion, filename,istrustworthy,application_title) VALUES (?, ?, ?, ?, ?, ?, ?)";

    int rc = sqlite3_prepare_v2(g_sqlite3_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("SQL: %s error:%s\n", sql, sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    dzlog_info("SqlAddAppInfo_V1 param.appId[%s],app[%s],version[%s],application_title[%s]", param.appId, app, version, application_title);
    // 绑定参数的值
    sqlite3_bind_text(stmt, 1, param.appId, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, param.fileId, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, app, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 4, version, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 5, filename, -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 6, 1);
    sqlite3_bind_text(stmt, 7, application_title, -1, SQLITE_STATIC);

    // 因为要3.14版本以上的sqlite支持，注释掉
    //  char *expanded_sql = sqlite3_expanded_sql(stmt);
    //  if (expanded_sql != NULL)
    //  {
    //      dzlog_debug("生成的 SQL 语句: %s\n", expanded_sql);
    //      sqlite3_free(expanded_sql);
    //  }

    // 执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("SQL error: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 重置预处理语句以便可重复使用
    sqlite3_reset(stmt);
    ret = true;

error:
    if(stmt)    
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }

    return ret;
}

/// @brief 插入app相关信息
/// @param param
/// @return
bool SqlAddAppInfo_V1(IOTA_APP_ADD_NEEDINFO param)
{
    int ret = false;

    sqlite3_stmt *stmt;
    const char *sql = "INSERT INTO APP_LIST (appid, fileid, appname, appversion, filename,istrustworthy,application_title) VALUES (?, ?, ?, ?, ?,?,?)";

    int rc = sqlite3_prepare_v2(g_sqlite3_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("SQL: %s error:%s\n", sql, sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 绑定参数的值
    char filename[64] = {0};
    strcat(filename, param.appName);
    strcat(filename, "_");
    strcat(filename, param.version);
    strcat(filename, ".tar.gz");
    sqlite3_bind_text(stmt, 1, param.appId, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, "BuiltInProgram", -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, param.appName, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 4, param.version, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 5, filename, -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 6, param.isTrustworthy);
    sqlite3_bind_text(stmt, 7, param.appName, -1, SQLITE_STATIC);
    // 执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("执行 SQL 语句出错: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 重置预处理语句以便可重复使用
    sqlite3_reset(stmt);
    ret = true;

error:
    if(stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }
    return ret;
}

//@brief 删除app相关信息
//@param param
//@return
bool SqlDeleteAppInfo(IOTA_APP_CTRL param, char *filename)
{
    bool ret = false;
    sqlite3_stmt *stmt;
    char *str = filename;
    char app[256];
    char version[256];

    const char *underscorePos = strchr(str, '_');
    if (underscorePos != NULL)
    {
        // 提取应用名
        size_t appLength = underscorePos - str;
        strncpy(app, str, appLength);
        app[appLength] = '\0';

        // 查找版本号的起始位置
        const char *versionStartPos = underscorePos + 1;
        const char *versionDelimiterPos = strchr(versionStartPos, '.');
        if (versionDelimiterPos != NULL)
        {
            // 提取版本号
            size_t versionLength = versionDelimiterPos - versionStartPos;
            strncpy(version, versionStartPos, versionLength);
            version[versionLength] = '\0';
        }
    }
    const char *sql = "DELETE  FROM APP_LIST WHERE appid=?";

    int rc = sqlite3_prepare_v2(g_sqlite3_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("SqlDeleteAppInfo SQL: %s error:%s\n", sql, sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 绑定参数的值

    sqlite3_bind_text(stmt, 1, param.appOldId, -1, SQLITE_STATIC);

    // 因为要3.14版本以上的sqlite支持，注释掉
    //  char *expanded_sql = sqlite3_expanded_sql(stmt);
    //  if (expanded_sql != NULL)
    //  {
    //      dzlog_debug("生成的 SQL 语句: %s\n", expanded_sql);
    //      sqlite3_free(expanded_sql);
    //  }

    // 执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("SqlDeleteAppInfo 执行 SQL 语句出错: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 重置预处理语句以便可重复使用
    sqlite3_reset(stmt);
    ret = true;
error:
    if (stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }

    return ret;
}

//@brief 删除app相关信息DELETE
//@param param
//@return
bool SqlDeleteAppInfoByAppName(IOTA_APP_CTRL param, char *filename)
{
    bool ret = false;
    sqlite3_stmt *stmt;
    char *str = filename;
    char app[256];
    char version[256];

    // sys.nfoam-V1.2.1-20250117.pack  单架构应用名规范:appname-version-date.pack   appmname_version.tar.gz
    char delimiter[] = "-";
    int MAX_TOKENS = 10;
    int MAX_TOKEN_LEN = 20;
    char tokens[10][20];
    int token_count = 0;
    // 使用strtok函数分割字符串
    char *token = strtok(str, delimiter);
    while (token != NULL && token_count < MAX_TOKENS)
    {
        strncpy(tokens[token_count], token, MAX_TOKEN_LEN - 1);
        tokens[token_count][MAX_TOKEN_LEN - 1] = '\0'; // 确保字符串以null结尾
        token_count++;
        token = strtok(NULL, delimiter);
    }
    if (token_count < 2)
    {
        // 包名并不符合规范
        strcpy(app, param.appName);
    }
    else
    {
        strcpy(app, tokens[0]);
    }


    const char *sql = "DELETE  FROM APP_LIST WHERE appname=?";

    int rc = sqlite3_prepare_v2(g_sqlite3_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("SqlDeleteAppInfoByAppName SQL: %s error:%s\n", sql, sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 绑定参数的值
    sqlite3_bind_text(stmt, 1, app, -1, SQLITE_STATIC);
    // sqlite3_bind_text(stmt, 2, param.appId, -1, SQLITE_STATIC);
    //  执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("SqlDeleteAppInfoByAppName 执行 SQL 语句出错: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 重置预处理语句以便可重复使用
    sqlite3_reset(stmt);
    ret = true;
error:
    if(stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }

    return ret;
}

/// @brief 查询appid
/// @param appid
/// @param appname
/// @return
bool SqlSearchAppidByVer(char *appid, char *appversion)
{
    bool ret = false;
    sqlite3_stmt *stmt;
    const char *selectQuery = "SELECT appid FROM APP_LIST WHERE appid = ? AND appversion = ?";
    int rc = sqlite3_prepare_v2(g_sqlite3_db, selectQuery, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法编译SQL语句: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    rc = sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_STATIC);
    rc = sqlite3_bind_text(stmt, 2, appversion, -1, SQLITE_STATIC);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法绑定参数: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    // 执行查询
    if ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        const char *sql_appid = (const char *)sqlite3_column_text(stmt, 0);
        if (strlen(sql_appid) != 0 && *sql_appid != '\0')
        {
            ret = true;
        }
    }
    else if (rc == SQLITE_DONE)
    {
    }
    else
    {
        dzlog_error("无法执行查询: %s\n", sqlite3_errmsg(g_sqlite3_db));
    }

error:
    if (stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }
    return ret;
}

/// @brief 查询appid
/// @param appid
/// @param appname
/// @return
bool SqlSearchAppid(APP_INFO *app, char *appname)
{
    bool ret = false;

    sqlite3_stmt *stmt;
    const char *selectQuery = "SELECT appid, appversion, istrustworthy ,application_title FROM APP_LIST WHERE appname = ?";
    int rc = sqlite3_prepare_v2(g_sqlite3_db, selectQuery, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法编译SQL语句: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    rc = sqlite3_bind_text(stmt, 1, appname, -1, SQLITE_STATIC);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法绑定参数: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    // 执行查询
    if ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        const char *sql_appid = (const char *)sqlite3_column_text(stmt, 0);
        const char *sql_appversion = (const char *)sqlite3_column_text(stmt, 1);

        if (strlen(sql_appid) != 0 && *sql_appid != '\0')
        {
            strcpy(app->appid, sql_appid);
            strcpy(app->appversion, sql_appversion);
            app->isTrustworthy = sqlite3_column_int(stmt, 2);
            strcpy(app->name, (const char *)sqlite3_column_text(stmt, 3));
        }
        ret = true;
    }
    else if (rc == SQLITE_DONE)
    {
        ret = true;
    }
    else
    {
        dzlog_error("无法执行查询: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

error:
    if(stmt)
    {
        // 释放资源
        sqlite3_finalize(stmt);
    }
    return ret;
}

/// @brief 查询containerid
/// @param containername
/// @param containername
/// @return
int SqlSearchContainerid(CONTAINER_INFO *container, char *containername)
{
    int ret = -1;
    sqlite3_stmt *stmt;
    const char *selectQuery = "SELECT TYPE, CONTAINERID, id FROM CONTAINER_LIST WHERE containername = ?";
    int rc = sqlite3_prepare_v2(g_sqlite3_db, selectQuery, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法编译SQL语句: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    rc = sqlite3_bind_text(stmt, 1, containername, -1, SQLITE_STATIC);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法绑定参数: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    // 执行查询
    if ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        const char *sql_type = (const char *)sqlite3_column_text(stmt, 0);
        const char *sql_containerid = (const char *)sqlite3_column_text(stmt, 1); // 平台侧所用id
        const char *id = (const char *)sqlite3_column_text(stmt, 2);              // 端侧docket所用id
        strcpy(container->type, sql_type);
        strcpy(container->containerid, sql_containerid);
        strcpy(container->id, id);
        ret = 0;
    }
    else if (rc == SQLITE_DONE)
    {
        dzlog_debug("未找到匹配的记录\n");
        ret = 0;
    }
    else
    {
        dzlog_error("无法执行查询: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    
error:
    // 释放资源
    if(stmt)
    {
        sqlite3_finalize(stmt);
    }
    return ret;
}
/// @brief 查询appname
/// @param appid
/// @param appname
/// @return
bool SqlSearchAppInfo(char *appid, char *appname)
{
    bool ret = false;

    sqlite3_stmt *stmt;
    const char *selectQuery = "SELECT * FROM APP_LIST WHERE appid = ?";
    int rc = sqlite3_prepare_v2(g_sqlite3_db, selectQuery, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法编译SQL语句: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    rc = sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_STATIC);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法绑定参数: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    // 执行查询
    if ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        const char *sql_appname = NULL;
        sql_appname = (const char *)sqlite3_column_text(stmt, 2);
        strcpy(appname, sql_appname);
        ret = true;
    }
    else if (rc == SQLITE_DONE)
    {
        dzlog_debug("未找到匹配的记录\n");
        goto error;
    }
    else
    {
        dzlog_error("无法执行查询: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    // 释放资源
error:
    if(stmt)
    {
        sqlite3_finalize(stmt);
    }
    return ret;
}
/// @brief 删除app
/// @param appid
/// @return
bool SqlDeleteApp(char *appid)
{
    bool ret = false;

    sqlite3_stmt *stmt;
    const char *selectQuery = "DELETE FROM APP_LIST WHERE appid = ?";
    int rc = sqlite3_prepare_v2(g_sqlite3_db, selectQuery, -1, &stmt, NULL);

    if (rc != SQLITE_OK)
    {
        dzlog_error("无法编译SQL语句: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    rc = sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_STATIC);
    if (rc != SQLITE_OK)
    {
        dzlog_error("无法绑定参数: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }

    // 执行 SQL 语句
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        dzlog_error("删除数据失败: %s\n", sqlite3_errmsg(g_sqlite3_db));
        goto error;
    }
    else
    {
        dzlog_info("成功删除appid %s", appid);
        ret = true;
    }
error:
    if (stmt)
    {
        // 释放语句对象
        sqlite3_finalize(stmt);
    }
    return ret;
}

bool JsonToStruct_AppDownload(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        if (cJSON_HasObjectItem(json, "requestId") && strlen(cJSON_GetObjectItem(json, "requestId")->valuestring) > 0)
        {
            pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        }
        else
        {
            pcStatusDecs->requestID = NULL;
        }

        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_APP_DOWNLOAD *st_param = pcStatusDecs->param;
            st_param->fileName = strdup(cJSON_GetObjectItem(param, "fileName")->valuestring);
            if (cJSON_HasObjectItem(param, "fileId"))
            {
                st_param->fileId = strdup(cJSON_GetObjectItem(param, "fileId")->valuestring);
            }
            else
            {
                st_param->fileId = NULL;
            }
            if (cJSON_HasObjectItem(param, "digest"))
            {
                st_param->digest = strdup(cJSON_GetObjectItem(param, "digest")->valuestring);
            }
            else
            {
                st_param->digest = NULL;
            }
            st_param->digestAlgorithm = strdup(cJSON_GetObjectItem(param, "digestAlgorithm")->valuestring);

            st_param->fileType = strdup(cJSON_GetObjectItem(param, "fileType")->valuestring);
            st_param->size = cJSON_GetObjectItem(param, "size")->valueint;
        }
        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool JsonToStruct_AppDownloadProgress(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_APP_DOWNLOAD_PROGRESS *st_param = pcStatusDecs->param;

            if (cJSON_HasObjectItem(param, "fileId"))
            {
                st_param->fileId = strdup(cJSON_GetObjectItem(param, "fileId")->valuestring);
            }
            if (cJSON_HasObjectItem(param, "appId"))
            {
                st_param->fileId = strdup(cJSON_GetObjectItem(param, "appId")->valuestring);
            }
        }

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool JsonToStruct_AppCtrl(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        if (cJSON_HasObjectItem(json, "requestId") && strlen(cJSON_GetObjectItem(json, "requestId")->valuestring) > 0)
        {
            pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        }
        else
        {
            pcStatusDecs->requestID = strdup("com.jxtech.iot_ops - applications");
        }

        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_APP_CTRL *st_param = pcStatusDecs->param;
            st_param->appId = strdup(cJSON_GetObjectItem(param, "appId")->valuestring);
            if (cJSON_HasObjectItem(param, "appOldId"))
            {
                st_param->appOldId = strdup(cJSON_GetObjectItem(param, "appOldId")->valuestring);
            }
            else
            {
                st_param->appOldId = NULL;
            }
            if (cJSON_HasObjectItem(param, "fileId"))
            {
                st_param->fileId = strdup(cJSON_GetObjectItem(param, "fileId")->valuestring);
            }
            else
            {
                st_param->fileId = NULL;
            }

            if (cJSON_HasObjectItem(param, "containerId"))
            {
                st_param->containerId = strdup(cJSON_GetObjectItem(param, "containerId")->valuestring);
            }
            else
            {
                st_param->containerId = NULL;
            }

            if (cJSON_HasObjectItem(param, "containerName"))
            {
                st_param->containerName = strdup(cJSON_GetObjectItem(param, "containerName")->valuestring);
            }
            else
            {
                st_param->containerName = NULL;
            }

            if (cJSON_HasObjectItem(param, "containerHyperv"))
            {
                st_param->containerHyperv = strdup(cJSON_GetObjectItem(param, "containerHyperv")->valuestring);
            }
            else
            {
                st_param->containerHyperv = NULL;
            }

            if (cJSON_HasObjectItem(param, "appName"))
            {
                st_param->appName = strdup(cJSON_GetObjectItem(param, "appName")->valuestring);
            }
            else
            {
                st_param->appName = NULL;
            }

            if (cJSON_HasObjectItem(param, "appLocated"))
            {
                st_param->appLocated = strdup(cJSON_GetObjectItem(param, "appLocated")->valuestring);
            }
            else
            {
                st_param->appLocated = NULL;
            }
        }

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool StructToJson_AppDownLoadRes(char **pcJson, ST_IOTA_LOG_RES *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *body = NULL;
    json = cJSON_CreateObject();
    body = cJSON_CreateObject();
    char cTime[128] = {0};
    int ret = systemDate2(cTime);
    if (pcStatusDecs)
    {
        // json
        cJSON_AddStringToObject(json, "mid", pcStatusDecs->iMid);
        cJSON_AddNumberToObject(json, "code", pcStatusDecs->code);
        cJSON_AddStringToObject(json, "deviceSn", pcStatusDecs->deviceSn);
        if (pcStatusDecs->replyId != NULL)
        {
            cJSON_AddStringToObject(json, "replyId", pcStatusDecs->replyId);
        }
        cJSON_AddStringToObject(json, "zone", pcStatusDecs->zone);
        cJSON_AddStringToObject(json, "node", pcStatusDecs->node);
        cJSON_AddStringToObject(json, "msgTime", cTime);
        cJSON_AddStringToObject(json, "deviceId", pcStatusDecs->deviceID);

        // body
        IOTA_APP_DOWNLOAD_PROGRESS *st_body = (IOTA_APP_DOWNLOAD_PROGRESS *)pcStatusDecs->body;
        cJSON_AddStringToObject(body, "fileId", st_body->fileId);
        cJSON_AddItemToObject(json, "body", body);

        *pcJson = cJSON_PrintUnformatted(json);

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool StructToJson_AppDownLoadProgressRes(char **pcJson, ST_IOTA_LOG_RES *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *body = NULL;
    json = cJSON_CreateObject();
    body = cJSON_CreateObject();

    char cTime[128] = {0};
    int ret = systemDate2(cTime);
    if (pcStatusDecs)
    {
        // json
        cJSON_AddStringToObject(json, "mid", pcStatusDecs->iMid);
        cJSON_AddNumberToObject(json, "code", pcStatusDecs->code);
        cJSON_AddStringToObject(json, "deviceSn", pcStatusDecs->deviceSn);
        cJSON_AddStringToObject(json, "replyId", pcStatusDecs->replyId);
        cJSON_AddStringToObject(json, "zone", pcStatusDecs->zone);
        cJSON_AddStringToObject(json, "node", pcStatusDecs->node);
        cJSON_AddStringToObject(json, "requestId", pcStatusDecs->requestID);
        cJSON_AddStringToObject(json, "msgTime", cTime);
        cJSON_AddStringToObject(json, "deviceId", pcStatusDecs->deviceID);

        // body
        IOTA_APP_DOWNLOAD_PROGRESS_RES *st_body = (IOTA_APP_DOWNLOAD_PROGRESS_RES *)pcStatusDecs->body;
        if (st_body != NULL)
        {
            cJSON_AddStringToObject(body, "appId", st_body->appId);
            cJSON_AddStringToObject(body, "filename", st_body->filename);
            cJSON_AddNumberToObject(body, "totalSize", st_body->totalSize);
            cJSON_AddNumberToObject(body, "size", st_body->size);
        }

        cJSON_AddItemToObject(json, "body", body);

        *pcJson = cJSON_PrintUnformatted(json);

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool StructToJson_AppCtrlRes(char **pcJson, ST_IOTA_LOG_RES *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *body = NULL;
    json = cJSON_CreateObject();
    body = cJSON_CreateObject();
    char cTime[128] = {0};
    int ret = systemDate2(cTime);
    if (pcStatusDecs)
    {
        // json
        cJSON_AddStringToObject(json, "mid", pcStatusDecs->iMid);
        cJSON_AddNumberToObject(json, "code", pcStatusDecs->code);
        cJSON_AddStringToObject(json, "deviceSn", pcStatusDecs->deviceSn);
        cJSON_AddStringToObject(json, "replyId", pcStatusDecs->replyId);
        cJSON_AddStringToObject(json, "zone", pcStatusDecs->zone);
        cJSON_AddStringToObject(json, "node", pcStatusDecs->node);
        cJSON_AddStringToObject(json, "requestId", pcStatusDecs->requestID);
        cJSON_AddStringToObject(json, "msgTime", cTime);
        cJSON_AddStringToObject(json, "deviceId", pcStatusDecs->deviceID);

        // body
        IOTA_APP_CTRL_RES *st_body = (IOTA_APP_CTRL_RES *)pcStatusDecs->body;
        cJSON_AddStringToObject(body, "appId", st_body->appId);
        if (st_body->appOldId != NULL)
        {
            cJSON_AddStringToObject(body, "appOldId", st_body->appOldId);
        }
        cJSON_AddItemToObject(json, "body", body);

        *pcJson = cJSON_PrintUnformatted(json);

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

/// @brief 下载微服务
/// @param pJson
/// @return
int AppDownLoad(char *pJson)
{
    dzlog_info("terminalAppDownLoad start ");
    ST_IOTA_LOG log;
    IOTA_APP_DOWNLOAD param;

    log.param = &param;
    JsonToStruct_AppDownload(pJson, &log);

    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = log.requestID;
    log_res.zone = log.zone;
    bool isError = false;
    if (param.fileId == NULL)
    {
        log_res.code = 403;
        isError = true;
        dzlog_error("fileid is null");
        goto Uerror;
    }
    int ret = checkAndCreateDirectory(APP_FILE_PATH);
    if (ret == 0)
    {
        log_res.code = 500;
        isError = true;
        dzlog_error("create directory error");
        goto Uerror;
    }

    MemoryStruct oDataChunk;
    oDataChunk.memory = malloc(1); // 初始化内存
    oDataChunk.size = 0;
    char filename[128] = {0};
    char filenametemp[128] = {0};
    IOTA_APP_DOWNLOAD_PROGRESS body; // 参数一样所以借用一下

    char fileid[100] = {0};
    strcpy(fileid, param.fileId);
    body.fileId = fileid;

    log_res.code = 100;
    log_res.body = &body;

    StructToJson_AppDownLoadRes(&psJson, &log_res);
    ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    free_s(psJson);
    // 文件名
    // 判断下文件名是否是以tar.gz结尾的
    if (strlen(param.fileName) >= 7)
    {
        if (strcmp(param.fileName + strlen(param.fileName) - 7, ".tar.gz") == 0)
        {
            sprintf(filename, "%s", param.fileName);
        }
        else
        {
            sprintf(filename, "%s.tar.gz", param.fileName);
        }
    }

    ProgressInfo info;

    strcpy(info.fileid, fileid);
    strcpy(info.filename, filename);
    strcpy(info.md5, param.digest);
    info.filesize = param.size;

    // 文件下载
    sprintf(filenametemp, "%s/%s", APP_FILE_PATH, filename);
    dzlog_info("AppDownLoad start 3311 filename:%s", filenametemp);
    ////增加尝试次数
    ret = -1;
    int ii = 0;
    for (ii = 0; ii < 3; ii++)
    {
        ret = file_download(filenametemp, &info);
        if (ret >= 0)
        {
            break;
        }
    }

    if (ret == -1)
    {
        dzlog_error("下载出错：无法连接到或登录到文件服务器");
        isError = true;
        log_res.code = 520;
        goto Uerror;
    }
    else if (ret == -2)
    {
        dzlog_error("下载出错：文件服务器无法查询到该文件");
        isError = true;
        log_res.code = 521;

        goto Uerror;
    }
    else if (ret == -3)
    {
        dzlog_error("下载出错：文件下载超时或出错");
        isError = true;
        log_res.code = 522;
        goto Uerror;
    }
    else if (ret == -4)
    {
        dzlog_error("下载出错：没有这个文件或id");
        isError = true;
        log_res.code = 523;
        goto Uerror;
    }
    else
    {
        // 校验sha256
        char hash[SHA256_DIGEST_LENGTH * 2 + 1];

        calculate_file_sha256(filenametemp, hash);
        if (strcmp(hash, param.digest) != 0)
        {
            log_res.code = 420;
            isError = true;
            dzlog_error("Verification error：%s", hash);
            goto Uerror;
        }
        dzlog_info("Download successful:%s", filenametemp);
        log_res.body = "success";
        log_res.code = 200;
        strcpy(fileid, param.fileId);
        body.fileId = fileid;
        log_res.body = &body;
        StructToJson_AppDownLoadRes(&psJson, &log_res);
        ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    }
    //}
Uerror:
    if (isError)
    {
        log_res.body = &body;
        StructToJson_AppDownLoadRes(&psJson, &log_res);
        ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    }
Ufree:
    dzlog_info("Download successful after return 0 11");
    free_s(log.iMid);
    free_s(log.deviceSn);
    free_s(log.deviceID);
    free_s(log.msgTime);
    free_s(log.node);
    free_s(log.requestID);
    free_s(log.Servicename);
    free_s(log.zone);
    free_s(oDataChunk.memory);
    free_s(psJson);

    free_s(param.digest);
    free_s(param.digestAlgorithm);
    free_s(param.fileId);
    // free_s(param->fileLink);
    free_s(param.fileName);
    free_s(param.fileType);
    free_s(pJson);
    dzlog_info("Download successful after return 0 44");
    return 0;
}

/// @brief 下载进度（废弃）
/// @param pJson
/// @return
int terminalAppDownLoadProgress(char *pJson)
{
    //     ST_IOTA_LOG log;
    //     IOTA_APP_DOWNLOAD_PROGRESS param;
    //     log.param = &param;
    //     JsonToStruct_AppDownload(pJson, &log);

    //     char *psJson;
    //     char uid[80] = {0};
    //     GF_GetGUID(uid);
    //     ST_IOTA_LOG_RES log_res;
    //     log_res.body = NULL;
    //     log_res.deviceID = log.deviceID;
    //     log_res.deviceSn = log.deviceSn;
    //     log_res.iMid = uid;
    //     log_res.node = log.node;
    //     log_res.replyId = log.iMid;
    //     log_res.requestID = log.requestID;
    //     log_res.zone = log.zone;
    //     bool isError = false;
    //     int isHas = 0;
    //     IOTA_APP_DOWNLOAD_PROGRESS_RES body;
    //     // 获取对应下载进度

    //     body.filename = info.filename;
    //     body.appId = info.fileid;
    //     body.size = info.downloadedBytes;
    //     body.totalSize = info.filesize;
    //     log_res.body = &body;
    //     log_res.code = 200;
    //     isHas = 1;

    //     if (isHas != 1)
    //     {
    //         log_res.body = NULL;
    //         log_res.code = 500;
    //     }

    //     StructToJson_AppDownLoadProgressRes(&psJson, &log_res);
    //     int ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));

    // Uerror:
    //     if (isError)
    //     {
    //         log_res.body = "progress error";
    //         StructToJson_AppDownLoadProgressRes(&psJson, &log_res);
    //         ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    //     }
    // Ufree:
    //     free_s(log.iMid);
    //     free_s(log.deviceSn);
    //     free_s(log.deviceID);
    //     free_s(log.msgTime);
    //     free_s(log.node);
    //     free_s(log.requestID);
    //     free_s(log.Servicename);
    //     free_s(log.zone);
    //     free_s(param.fileId);
    //     free_s(psJson);

    return 0;
}

int terminalAppCtrl(char *pJson, int action)
{
    FILE *fp = NULL;
    ST_IOTA_LOG log;
    IOTA_APP_CTRL param;
    log.param = &param;
    JsonToStruct_AppCtrl(pJson, &log);
    char *psJson;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = log.requestID;
    log_res.zone = log.zone;
    bool isError = false;
    char cmd[128] = {0};
    int uninstall = 0;
    IOTA_APP_CTRL_RES body;
    body.appId = param.appId;
    body.appOldId = NULL;
    log_res.body = &body;

    int ret = 0;
    char appname[100] = {0};
    // 找到对应的文件id查看文件信息 只跟下载有关
    // int no = 0;
    // if (action == 1 || action == 5)
    // {
    //     for (no = 0; no < 20; no++)
    //     {
    //         if (strcmp(info.fileid, param.fileId) == 0)
    //         {
    //             break;
    //         }
    //     }
    // }
    switch (action)
    {
    case 1:
    {
        // 安装通过ota升级的方式安装所以此功能被废弃，暂时随便写个appname保证编译通过
        sprintf(cmd, "cd /userdata/tmp/package;appm -i -p %s", param.appName);
        SqlDeleteAppInfoByAppName(param, param.appName); // 当db中已经有同名的记录，需要删除
        if (SqlAddAppInfo(param, param.appName) == false)
        {
            dzlog_error("install app error");
            log_res.code = 504;
            isError = true;
            goto Uerror;
        }
    }
    break;
    case 2:
    {
        if (SqlSearchAppInfo(param.appId, appname))
        {
            sprintf(cmd, "appm -u -n %s", appname);
            uninstall = 1;
        }
        else
        {
            dzlog_error("can not find app %s", param.appId);
            log_res.code = 509;

            // 找不到，当卸载成功，返回200
            log_res.code = 200;
            isError = true;
            goto Uerror;
        }
    }
    break;
    case 3:
        if (SqlSearchAppInfo(param.appId, appname))
        {
            sprintf(cmd, "appm -s -n %s", appname);
        }
        else
        {
            dzlog_error("can not find app %s", param.appId);
            log_res.code = 505;
            isError = true;
            goto Uerror;
        }
        break;
    case 4:
        if (SqlSearchAppInfo(param.appId, appname))
        {
            sprintf(cmd, "appm -S -n %s", appname);
        }
        else
        {
            dzlog_error("can not find app %s", param.appId);
            log_res.code = 506;
            isError = true;
            goto Uerror;
        }
        break;
    case 5:
    {
        sprintf(cmd, "cd /userdata/tmp/package;appm -i -p %s", param.appName);
        if (SqlAddAppInfo(param, param.appName) == false)
        {
            dzlog_error("update app error");
            log_res.code = 504;
            isError = true;
            goto Uerror;
        }
        if (SqlDeleteAppInfo(param, param.appName) == 0)
        {
            dzlog_error("ipdate app error");
            // log_res.code = 504;
            // isError = true;
            // goto Uerror;
        }
        body.appOldId = param.appOldId;
    }
    break;
    default:
        dzlog_error("terminalAppCtrl Unsupported Instructions，%d", action);
        log_res.code = 500;
        isError = true;
        goto Uerror;
        break;
    }
    dzlog_info("terminalAppCtrl cmd[%s]", cmd);

    //新增逻辑2025.6.18
    //appm执行失败添加重试3次
    //每次重试间隔0.5秒
    int retry_num = 0;
    bool is_appm_success = false;
    do
    {
        fp = popen(cmd, "r");
        if (fp == NULL)
        {
            dzlog_error("cannot install app");
            log_res.code = 500;
            isError = true;
            goto Uerror;
        }

        char buffer[1024];
        while (fgets(buffer, sizeof(buffer), fp) != NULL)
        {
            // 处理命令输出
            dzlog_info("terminalAppCtrl message = %s", buffer);
			is_appm_success = true;
        }
        is_appm_success = true;
        if(is_appm_success)
        {
            break;
        }
        usleep(500 * 1000);
        retry_num++;

    } while (retry_num < 3);

    // 用不上所以注释掉
    //  if (action == 1 || action == 5)
    //  {
    //      char app[100];
    //      const char *underscorePos = strchr(info.filename, '_');
    //      if (underscorePos != NULL)
    //      {
    //          size_t appLength = underscorePos - info.filename;
    //          strncpy(app, info.filename, appLength);
    //          app[appLength] = '\0';
    //      }
    //      char trinity[256] = "chown -R tmp:tmp /userdata/tmp/app/";
    //      strcat(trinity, app);
    //      system(trinity);
    //  }

    if(is_appm_success)
    {
        log_res.code = 200;
    }
    else
    {
        log_res.code = 503;
        isError = true;
        goto Uerror;
    }

    StructToJson_AppCtrlRes(&psJson, &log_res);
    IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    if (uninstall)
    {
        SqlDeleteApp(param.appId);
    }
    // 清空对应download信息
    // if (action == 1)
    // {
    //     memset(&info, 0, sizeof(DownloadInfo));
    // }

Uerror:
    if (isError)
    {
        StructToJson_AppCtrlRes(&psJson, &log_res);
        ret = IOTA_SendMqtt("/v1/devices/app/response", psJson, strlen(psJson));
    }
Ufree:
    free_s(log.iMid);
    free_s(log.deviceSn);
    free_s(log.deviceID);
    free_s(log.msgTime);
    free_s(log.node);
    free_s(log.requestID);
    free_s(log.Servicename);
    free_s(log.zone);
    free_s(param.appId);
    free_s(param.appOldId);
    free_s(param.fileId);
    free_s(param.containerId);
    free_s(param.containerName);
    free_s(param.containerHyperv);
    free_s(param.appName);
    free_s(param.appLocated);
    
    if (fp != NULL)
    {
        pclose(fp);
    }
    free(psJson);
    return 0;
}

int terminalAppDownLoad(char *pJson)
{
    // 分线程
    pthread_t thread;
    pthread_attr_t attr;
    char *psJson = strdup(pJson);
    // 初始化线程属性
    pthread_attr_init(&attr);

    // 将线程设置为分离状态
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    // 创建线程
    pthread_create(&thread, &attr, AppDownLoad, psJson);
    // 销毁线程属性对象
    pthread_attr_destroy(&attr);
    return 0;
}

int update_app_status_v1_pthread(char* pJson)
{
    sleep(1);
    char uuid[64] = { 0 };
    GF_GetGUID(uuid);
    dzlog_info("update_app_status_pthread start");
    int ret = terminalAppRuntimeData(uuid, g_mqtt_ob.clientInfo.device_id, 1); // 系统运行数据上报
    dzlog_info("update_app_status_pthread end");

    //GF_GetGUID(uuid);
    //dzlog_info("terminalprocessEvent start");
    //ret = terminalprocessEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1); // 系统运行数据上报
    //dzlog_info("terminalprocessEvent end");

    pthread_mutex_lock(&app_status_thread_mutex);
    app_status_thread_running = false;
    pthread_mutex_unlock(&app_status_thread_mutex);

    return 0;
}

int app_commond(char* pcJson)
{
    dzlog_info("app_commond start");
    cJSON* json = NULL;
    char cmd[32] = { 0 };
    json = cJSON_Parse(pcJson);
    if (json)
    {
        strncpy(cmd, cJSON_GetObjectItem(json, "cmd")->valuestring, sizeof(cmd));
        dzlog_info("app_commond cmd[%s] ", cmd);
        if (strstr(cmd, "actionAppDownload"))
        {
            terminalAppDownLoad(pcJson);
        }
        else if (strstr(cmd, "getAppDownloadStatus"))
        {
            terminalAppDownLoadProgress(pcJson);
        }
        else if (strstr(cmd, "actionAppInstall"))
        {
            terminalAppCtrl(pcJson, 1);
        }
        else if (strstr(cmd, "actionAppUninstall"))
        {
            terminalAppCtrl(pcJson, 2);
        }
        else if (strstr(cmd, "actionAppStart"))
        {
            terminalAppCtrl(pcJson, 3);
        }
        else if (strstr(cmd, "actionAppStop"))
        {
            terminalAppCtrl(pcJson, 4);
        }
        else if (strstr(cmd, "actionAppUpdate"))
        {
            terminalAppCtrl(pcJson, 5);
        }
        cJSON_Delete(json);

        pthread_mutex_lock(&app_status_thread_mutex);
        if (app_status_thread_running)
        {
            dzlog_info("app_status_thread_running already running! Aborting.");
        }
        else
        {
            app_status_thread_running = true;

            //由于实际业务执行耗时较长，所以起线程执行业务
            pthread_t thread;
            pthread_attr_t attr;
            // 初始化线程属性
            pthread_attr_init(&attr);
            // 将线程设置为分离状态
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

            // 创建线程
            pthread_create(&thread, &attr, update_app_status_v1_pthread, NULL);
            // 销毁线程属性对象
            pthread_attr_destroy(&attr);
        }
        pthread_mutex_unlock(&app_status_thread_mutex);
    }
    return 0;
}
